﻿using NCS.IConnect.Core.Utilities;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Net.Http;
using System.Web;
using System.Web.Http.Controllers;

namespace NCS.IConnect.Core.WebApi.Validation
{
    /// <summary>
    /// This attribute is used to validate required field based on request's HTTP method. 
    /// </summary>
    public class RequiredIfAttribute : ConditionalValidationAttribute
    {
        private RequiredAttribute requiredAttribute;

        /// <summary>
        /// The <see cref="HttpMethod"/>s to be used to determine if target field is required.
        /// </summary>
        public HttpMethod[] HttpMethods { get; private set; }

        /// <summary>
        /// If false, the target field is only required when request's HTTP method is one of the HttpMethods. Otherwise, it is only required when the HTTP method is not any one of the HttpMethods.
        /// </summary>
        public bool Negated { get; set; }

        /// <summary>
        /// Create a new <see cref="RequiredIfAttribute"/>.
        /// </summary>
        /// <param name="httpMethods">The HTTP method names seperated by ","./// </param>
        public RequiredIfAttribute(string httpMethods)
        {
            Guard.ArgumentNotNull(httpMethods, "httpMethods");
            this.HttpMethods = httpMethods.Split(',').Select(it => new HttpMethod(it)).ToArray();
        }

        /// <summary>
        /// Determine whether to perform validation.
        /// </summary>
        /// <param name="actionContext">The current <see cref="HttpActionContext"/>.</param>
        /// <returns>A <see cref="bool"/> value indicating whether to perform validation.</returns>
        public override bool WillValidate(HttpActionContext actionContext)
        {
            return (this.HttpMethods.Contains(actionContext.Request.Method) && !this.Negated) ||
                (!this.HttpMethods.Contains(actionContext.Request.Method) && this.Negated);
        }

        /// <summary>
        /// Create a <see cref="ValidationAttribute"/> to perform validation.
        /// </summary>
        /// <returns>The created <see cref="ValidationAttribute"/>.</returns>

        public override ValidationAttribute CreateValidationAttribute()
        {
            if (null != requiredAttribute)
            {
                return requiredAttribute;
            }

            requiredAttribute = new RequiredAttribute();

            if (!string.IsNullOrEmpty(this.ErrorMessage))
            {
                requiredAttribute.ErrorMessage = this.ErrorMessage;
            }

            if (!string.IsNullOrEmpty(this.ErrorMessageResourceName))
            {
                requiredAttribute.ErrorMessageResourceName = this.ErrorMessageResourceName;
            }

            if (null != this.ErrorMessageResourceType)
            {
                requiredAttribute.ErrorMessageResourceType = this.ErrorMessageResourceType;
            }
            return requiredAttribute;
        }
    }
}